package com.gitee.mazhenggg.demo.gateway.filter;


import com.alibaba.cloud.commons.lang.StringUtils;
import com.gitee.mazhenggg.demo.common.constant.TokenConstants;
import com.gitee.mazhenggg.demo.gateway.exception.AccessException;
import com.gitee.mazhenggg.demo.gateway.service.AuthService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashSet;
import java.util.Set;

import static com.gitee.mazhenggg.demo.common.constant.TokenConstants.AUTH_TOKEN;


@Slf4j
public class AccessFilter implements GlobalFilter {


    private static final AntPathMatcher pathMatch = new AntPathMatcher();

    public boolean ignoreAuthentication(String requestPath) {
        Set<String> authorityIgnores = new HashSet<>();

        authorityIgnores.add("/");
        authorityIgnores.add("/**/auth/**");
        authorityIgnores.add("/**/login/**");
        authorityIgnores.add("/**/logout/**");

        authorityIgnores.add("/error");
        authorityIgnores.add("/favicon.ico");
        authorityIgnores.add("/**/actuator/**");
        authorityIgnores.add("/**/v2/api-docs/**");
        authorityIgnores.add("/**/swagger-resources/**");
        authorityIgnores.add("/**/webjars/**");
        authorityIgnores.add("/**/doc.html/**/");
        authorityIgnores.add("/**/swagger-ui.html/**/");

        authorityIgnores.add("/**/un/**");

        return authorityIgnores.stream()
                .filter(r -> pathMatch.match(r, requestPath))
                .findFirst().isPresent();
    }


    @Autowired
    private AuthService authService;


    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String authToken = request.getHeaders().getFirst(TokenConstants.AUTH_TOKEN);
        String requestPath = request.getURI().getPath();

        if (!ignoreAuthentication(requestPath)) {
            // 验证token
            if (StringUtils.isBlank(authToken)) {
                log.error("requestPath:{},headers:{}, 请求未携带token信息", requestPath, request.getHeaders());
                throw new AccessException("token not found!");
            }
//            try {
//                validateToken(authToken);
//            } catch (ExpiredJwtException e) {
//                throw new AccessException("token expired!");
//            } catch (Exception e) {
//                throw new AccessException("token invalid!");
//            }
            // token是否失效
            String jwt = authService.verifyToken(TokenConstants.AUTH_TOKEN,authToken);
            if(StringUtils.isBlank(jwt)){
                                log.error("requestPath:{},headers:{}, token无效", requestPath, request.getHeaders());
                throw new AccessException("token invalid!");
            }else {
                ServerHttpRequest accessToken = request.mutate().header(TokenConstants.ACCESS_TOKEN, jwt).build();
                exchange = exchange.mutate().request(accessToken).build();
            }
//            if (!result.getStatusCode().equals(200)) {
//                log.error("requestPath:{},headers:{}, token无效", requestPath, request.getHeaders());
//                //throw new TepAccessDeniedException(ResultCode.TOKEN_INVALID);
//            } else {
//                //向headers中放入jwtToken，记得build
//                String jwt = result.getBody().toString();
//
//            }

        }
        return chain.filter(exchange);
    }
}
